import { Asset, Constructor, resources, error, assetManager, SpriteAtlas, SpriteFrame } from "cc";
import Singleton from "../Base/Singleton";

export class ResourceManager extends Singleton {
    static get Instance() {
        return super.GetInstance<ResourceManager>();
    }

    // 单一内存缓存（存储所有资源）
    private resourceCache = new Map<string, Asset>();

    /**
     * 统一路径处理
     */
    private normalizePath(path: string): string {
        const subResourceSuffixes = ['/spriteFrame', '/texture', '/default'];
        let normalizedPath = path;
        
        for (const suffix of subResourceSuffixes) {
            if (normalizedPath.endsWith(suffix)) {
                normalizedPath = normalizedPath.slice(0, -suffix.length);
                break;
            }
        }
        return normalizedPath;
    }

    /**
     * 核心修复：加载资源
     * 逻辑：
     * 1. 如果是普通资源，正常加载。
     * 2. 如果是图集(SpriteAtlas)：
     *    - 情况A (构建后): 图集里有图 -> 建立索引 -> 完成。
     *    - 情况B (编辑器预览): 图集里没图(0帧) -> **自动回退调用 loadDir 加载该目录下的散图** -> 完成。
     */
    loadRes<T extends Asset>(path: string, type?: Constructor<T>): Promise<T> {
        const normalizedPath = this.normalizePath(path);
        console.log(`[ResourceManager] 图集加载排查path: ${path}`);
        console.log(`[ResourceManager] 图集加载排查normalizedPath: ${normalizedPath}`);
        
        // 缓存命中直接返回
        if (this.resourceCache.has(normalizedPath)) {
            console.log(`[ResourceManager] 图集加载排查: ${normalizedPath} 已缓存`);
            return Promise.resolve(this.resourceCache.get(normalizedPath) as unknown as T);
        }

        return new Promise<T>((resolve, reject) => {
            resources.load(path, type as any, async (err, asset) => {
                if (err) {
                    console.error(`[ResourceManager] 加载失败: ${path}`, err);
                    reject(err);
                    return;
                }

                // 存入缓存
                this.resourceCache.set(normalizedPath, asset);

                // === 针对图集的特殊处理 ===
                if (asset instanceof SpriteAtlas) {
                    const frames = asset.getSpriteFrames();
                    console.log(`[ResourceManager] 图集加载排查asset: `, asset);
                    console.log(`[ResourceManager] 图集加载排查frames: `, frames);
                    
                    if (frames.length > 0) {
                        // --- 情况A：图集正常 (构建后) ---
                        console.log(`[ResourceManager] 图集生效: ${path}, 包含 ${frames.length} 帧`);
                        // 获取图集所在的文件夹路径
                        const dirPath = path.substring(0, path.lastIndexOf('/'));
                        
                        frames.forEach(frame => {
                            // 建立索引，让 getRes 能直接找到小图
                            const framePath = `${dirPath}/${frame.name}`;
                            this.resourceCache.set(framePath, frame);
                            this.resourceCache.set(this.normalizePath(framePath), frame);
                        });
                        resolve(asset as unknown as T);
                    } else {
                        // --- 情况B：图集为空 (编辑器预览模式) ---
                        // console.warn(`[ResourceManager] 预览模式检测: 图集 ${path} 为空，自动执行散图回退加载...`);
                        
                        // 获取图集所在的文件夹路径 (例如 pic/enemy)
                        const dirPath = path.substring(0, path.lastIndexOf('/'));
                        console.warn(`[ResourceManager] 图集加载排查frames=0, dirPath: `, dirPath);
                        
                        try {
                            // 强制加载该目录下的所有 SpriteFrame
                            await this.loadDir(dirPath, SpriteFrame);
                            // console.log(`[ResourceManager] 预览模式补救成功: 已加载散图 ${dirPath}`);
                        resolve(asset as unknown as T);
                        } catch (loadErr) {
                            console.error(`[ResourceManager] 预览模式补救失败: ${dirPath}`, loadErr);
                            // 即使散图加载失败，也返回图集对象，防止卡死
                        resolve(asset as unknown as T);
                        }
                    }
                } else {
                    // 非图集资源，直接返回
                        resolve(asset as unknown as T);
                }
            });
        });
    }

/**
     * 加载目录下所有资源 (修复版：能够保持正确的子目录结构)
     * @param dirPath 目录路径
     * @param type 资源类型
     */
    async loadDir<T extends Asset>(dirPath: string, type?: Constructor<T>): Promise<T[]> {
        console.log(`[ResourceManager] 图集加载排查，开始加载目录: ${dirPath}`);
        return new Promise((resolve, reject) => {
            // 1. 关键步骤：先获取该目录下所有文件的信息（包含准确的相对路径）
            const infos = resources.getDirWithPath(dirPath, type as any);
            
            if (infos.length === 0) {
                console.warn(`[ResourceManager] 目录为空或不存在: ${dirPath}`);
                resolve([]);
                return;
            }

            // 2. 提取所有准确的路径
            const paths = infos.map(info => info.path);

            // 3. 批量加载这些路径
            // 注意：resources.load 支持传入路径数组，且回调中 assets 数组的顺序与 paths 一致
            resources.load(paths, type as any, (err, assets) => {
                if (err) {
                    console.error(`[ResourceManager] 目录加载失败: ${dirPath}`, err);
                    reject(err);
                    return;
                }

                console.log(`[ResourceManager] 图集加载排查，resources.load path`, paths);
                
                // 4. 使用准确的路径进行缓存
                assets.forEach((asset, index) => {
                    const fullPath = paths[index]; // 这里拿到的就是 pic/enemy/enemy8/die/1 这种完整路径
                    this.resourceCache.set(fullPath, asset);
                    this.resourceCache.set(this.normalizePath(fullPath), asset);
                    console.log(`[ResourceManager] 图集加载排查，assets`, asset);
                    console.log(`[ResourceManager] 图集加载排查，fullPath`, fullPath);



                });
                
                console.log(`[ResourceManager] 图集加载排查，目录加载并索引成功: ${dirPath}, 数量: ${assets.length}`);

                //console.log(`[ResourceManager] 图集加载排查，,asset`, assets);
                resolve(assets as T[]);
            });
        });
    }

    /**
     * 批量加载
     */
    public async loadResArray<T extends Asset>(paths: string[], type: Constructor<T>): Promise<void> {
        const promises = paths.map(path => this.loadRes(path, type).catch(e => console.warn(e)));
        await Promise.all(promises);
    }

    /**
     * 获取单个资源
     */
    getRes<T extends Asset>(path: string, type?: Constructor<T>): T | null {
        const normalizedPath = this.normalizePath(path);
        const asset = this.resourceCache.get(normalizedPath);
        
        // 如果还是没找到，尝试用原始路径找一次
        if (!asset) {
            const rawAsset = this.resourceCache.get(path);
            if(rawAsset) return rawAsset as T;
        }

        return (asset as T) || null;
    }

    /**
     * 获取目录资源 (供 State.ts 使用)
     * 逻辑：优先查图集内容 -> 其次查散图缓存
     */
    getDirRes<T extends Asset>(dirPath: string): T[] {
        const results: T[] = [];
        let foundInAtlas = false;

        // 1. 尝试从图集里找 (构建后生效)
        this.resourceCache.forEach((asset) => {
            if (asset instanceof SpriteAtlas) {
                const frames = asset.getSpriteFrames();
                if (frames.length > 0) {
                    // 标准化路径分隔符
                    const cleanDirPath = dirPath.replace(/\\/g, '/');
                    
                    frames.forEach(frame => {
                        const cleanFrameName = frame.name.replace(/\\/g, '/');
                        // 宽松匹配：只要图集里的帧名字包含在请求路径里 (例如 "enemy5/die" 在 "pic/enemy/enemy5/die" 中)
                        // 去掉帧名字的文件名部分进行目录匹配
                        const frameDirIndex = cleanFrameName.lastIndexOf('/');
                        if (frameDirIndex !== -1) {
                            const frameDir = cleanFrameName.substring(0, frameDirIndex);
                            if (cleanDirPath.endsWith(frameDir) || cleanDirPath.includes(frameDir)) {
                                results.push(frame as unknown as T);
                                foundInAtlas = true;
                            }
                        }
                    });
                }
            }
        });

        if (foundInAtlas && results.length > 0) {
            results.sort((a: any, b: any) => this.naturalSort(a.name, b.name));
            return results;
        }

        // 2. 回退：从散图缓存里找 (预览模式生效)
        // 因为 loadRes 在预览模式下会自动调用 loadDir，所以散图已经在 resourceCache 里了
        this.resourceCache.forEach((asset, key) => {
            // 检查 key 是否以 dirPath 开头
            // 例如 key: "pic/enemy/enemy5/die/1"
            // dirPath: "pic/enemy/enemy5/die"
            if (key.startsWith(dirPath + '/') || key === dirPath) {
                results.push(asset as T);
            }
        });
        
        if (results.length > 0) {
            results.sort((a: any, b: any) => this.naturalSort(a.name, b.name));
        } else {
            console.warn(`[ResourceManager] getDirRes 未找到任何资源: ${dirPath}`);
        }

        return results;
    }

    private naturalSort(a: string, b: string): number {
        return a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' });
    }

    // ... 保持其他辅助方法 (isLoaded, releaseRes 等) 不变 ...
    getResourceCache(): Map<string, Asset> {
        return this.resourceCache;
    }
	
    /**
     * 检测资源是否已加载
     * @param path 资源路径
     */
    isLoaded(path: string): boolean {
        console.log(`[ResourceManager] 图集加载排查 检测资源是否已加载: ${path}`);
        return this.resourceCache.has(this.normalizePath(path));
    }

}

export const resMgr = ResourceManager.Instance;